/*
 * @Author: NingJian
 * @Date: 2021-09-16 15:31:23
 * @LastEditTime: 2021-09-17 11:30:35
 * @LastEditors: NingJian
 * @Description: 
 * @FilePath: /cmodel_r=2^128/homo_block.h
 * 
 */

#pragma once

#include <iostream>
#include <vector>
#include <stdint.h>

using namespace std;


enum CAL_MODE
{
    //模乘/模幂；
    CAL_MUL_OR_EXP = 0b000,
    // 模乘之和；
    CAL_MUL_SUM = 0b001,
    // 模幂之积；
    CAL_EXP_MUL = 0b010,
    // 模乘之和+acca clear；
    CAL_MUL_SUM_ACCA = 0b011,
    // 模幂之积+accm clear；
    CAL_EXP_MUL_ACCM = 0b100
};

enum OP_CODE
{
    //空操作
    OP_NULL = 0b0000,
    // 模乘操作；
    OP_MUL = 0b0001,
    // 模幂操作；
    OP_EXP = 0b0010,
    // 模乘之和操作；
    OP_MUL_SUM = 0b0011,
    // 模幂之积；
    OP_EXP_MUL = 0b0100,
    // 模乘和模幂操作提供共同的模数p、nsqure（这个操作单独一帧数据）
    OP_SET = 0b0111,
    // 将ACCA的值清零，并将原始值输出
    OP_MUL_SUM_ACCA = 0b1000,
    // 将ACCM的值清零，并将原始值输出
    OP_EXP_MUL_ACCM = 0b1001
};

enum PBitCount
{
    PB_512 = 0b001,
    PB_1024 = 0b010,
    PB_2048 = 0b011,
    PB_3072 = 0b100,
    PB_4096 = 0b101,
};

enum EBitCount
{
    EB_64 = 0b000,
    EB_128 = 0b001,
    EB_256 = 0b010,
    EB_512 = 0b011,
    EB_1024 = 0b100,
    EB_2048 = 0b101,
    EB_3072 = 0b110,
    EB_4096 = 0b111,
};


class HomoFrameHead
{
private:
    uint8_t id;
    OP_CODE opcode;
    PBitCount pbc;
    EBitCount ebc;

public:
    void init(uint8_t id, OP_CODE opcode, PBitCount pbc, EBitCount ebc);
    vector<uint8_t> get_raw_data();
};

class HomoFrame
{
private:
    HomoFrameHead head;
    vector<uint8_t> number_1;
    vector<uint8_t> number_2;

public:
    void init(uint8_t id, OP_CODE opcode, PBitCount pbc, EBitCount ebc, vector<uint8_t> &number_1, vector<uint8_t> &number_2);
    vector<uint8_t> get_raw_data();
};


class HomoBlockHead
{
private:
    uint16_t length;
    CAL_MODE cal_mode;
    uint8_t frame_num;

public:
    void init(CAL_MODE cal_mode);
    void set_prarms(uint16_t length, uint8_t frame_number);
    vector<uint8_t> get_raw_data();
};


class HomoBlock
{
private:
    HomoBlockHead head;
    vector<HomoFrame> frames;
    uint32_t checksum;

public:
    void init(CAL_MODE cal_mode);
    void add_frame(HomoFrame &frame);
    vector<uint8_t> get_raw_data(bool is_result = false);
};




